<?php
/**
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-05-26
 * Time: 10:55
 */

namespace app\common\model;


use app\common\exception\ParameterException;
use think\model\concern\SoftDelete;
use app\api\validate\mp\v1\User as ApiUserValidate;
use WXMPCrypt\WXBizDataCrypt;

class WeChatUser extends BaseModel
{
    protected $hidden = ['update_time', 'delete_time'];

    // 使用软删除
    use SoftDelete;
    protected $deleteTime = 'delete_time';

    public function admin()
    {
        // belongsToMany('关联模型','中间表','外键','关联键');
        // 关联模型（必须）：关联模型类名
        // 中间表：默认规则是当前模型名+_+关联模型名 （可以指定模型名）
        // 外键：中间表的当前模型外键，默认的外键名规则是关联模型名+_id
        // 关联键：中间表的当前模型关联键名，默认规则是当前模型名+_id
        return $this->belongsToMany('\\app\\admin\\model\\Admin', '\\app\\admin\\model\\AdminWeChatUser', 'user_id', 'we_chat_user_id');
    }

    public function setNickNameAttr($value)
    {
        if (!empty($value)) {
            return base64_encode($value);
        }
        return $value;
    }

    public function getNickNameAttr($value)
    {
        if (!empty($value)) {
            return base64_decode($value);
        }
        return $value;
    }

    /**
     * 获取微信小程序用户的分页数据
     * @param array $params
     * @return \think\Paginator
     */
    public static function getPaginationList(array $params)
    {
        static::validatePaginationData($params);

        $static = new static();

        $static = $static->where('nick_name', '<>', '')
            ->order('create_time', 'desc');

        foreach ($params as $name => $value) {
            $value = trim($value);
            switch ($name) {
                case 'nick_name' :
                    if (!empty($value)) {
                        $likeText = "from_base64(nick_name) like '%{$value}%'";
                        $static = $static->whereRaw($likeText);
                    }
                    break;
                case 'phone_number' :
                    if (!empty($value)) {
                        $likeText = '%' . $value . '%';
                        $static = $static->whereLike('phone_number', $likeText);
                    }
                    break;
                case 'gender' :
                    if (!empty($value)) {
                        $static = $static->where('gender', '=', intval($value));
                    }
                    break;
                case 'form':
                    if (!empty($value)) {
                        $static = $static->where('form', '=', intval($value));
                    }
                    break;
                case 'sort_order':
                    if (!empty($value)) {
                        $static = $static->order($params['sort_prop'], $value == 'descending' ? 'desc' : 'asc');
                    }
                    break;
            }
        }

        return $static
            ->paginate([
                'page' => $params['page'],
                'list_rows' => $params['limit']
            ], false);
    }

    /**
     * 根据用户名和openid查找用户
     * @param $param
     * @return array
     */
    public static function getUserInfoWithNickNameOrOpenID($param)
    {
        if (empty($param)) {
            return [];
        }
        $like_text = '%' . $param . '%';
        $user = static::where(function ($query) use ($like_text) {
            $query->whereRaw("from_base64(nick_name) like '{$like_text}'")
                ->whereOr('openid','like',$like_text);
        })
            ->where([['nick_name','<>','']])
            ->field('id, nick_name, avatar_url')
            ->select();

        return $user->isEmpty() ? [] : $user->toArray();
    }

    /**
     * 检查用户是否存在
     * @param $open_id
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function checkUserIsExist($open_id) {
        $user = static::where([['openid','=',$open_id]])
            ->find();

        if ($user) {
            return true;
        }
        return false;
    }

    /**
     * 根据open_id添加用户
     * @param $open_id
     * @param int $status
     * @return mixed
     */
    public static function addUserWithOpenID($open_id, $union_id = '', $status = 0)
    {
        $user = null;
        // 如果union_id不为空，则先判断数据库中是否有对应的用户
        if (!empty($union_id)) {
            $user = static::where([['unionid','=',$union_id]])
                ->find();
        }

        if ($user) {
            $user->allowField(['openid','status'])
                ->save([
                    'openid' => $open_id,
                    'status' => $status,
                ]);
        } else {
            $user = self::create([
                'openid' => $open_id,
                'unionid' => $union_id,
                'status' => $status,
            ]);
        }

        return $user->id;
    }

    /**
     * 通过微信网站应用添加用户信息
     * @param $user_data
     * @return mixed
     */
    public static function addUserByWebApp($user_data)
    {
        // 先判断当前当前用户的unionid是否已经存在数据库中，如果存在则只更新
        $user = null;
        if (isset($user_data['unionid']) && !empty($user_data['unionid'])) {
            $user = static::where([['unionid','=',$user_data['unionid']]])
                ->find();
        }
        if ($user) {
            $user->allowField(['web_openid'])
                ->save([
                    'web_openid' => $user_data['openid']
                ]);
        } else {
            $user = self::create([
                'web_openid' => $user_data['openid'],
                'unionid' => $user_data['unionid'],
                'nick_name' => $user_data['nickname'],
                'avatar_url' => $user_data['headimgurl'],
                'gender' => $user_data['sex'],
                'from' => 3
            ]);
        }

        return $user->id;
    }

    /**
     * 通过微信公众号网页添加用户信息
     * @param $user_data
     * @return mixed
     */
    public static function addUserByOCOAWebApp($user_data)
    {
        // 先判断当前当前用户的unionid是否已经存在数据库中，如果存在则只更新
        $user = null;
        if (isset($user_data['unionid']) && !empty($user_data['unionid'])) {
            $user = static::where([['unionid','=',$user_data['unionid']]])
                ->find();
        }
        if ($user) {
            $user->allowField(['oc_openid'])
                ->save([
                    'oc_openid' => $user_data['openid']
                ]);
        } else {
            $user = self::create([
                'oc_openid' => $user_data['openid'],
                'unionid' => $user_data['unionid'],
                'nick_name' => $user_data['nickname'],
                'avatar_url' => $user_data['headimgurl'],
                'gender' => $user_data['sex'],
                'from' => 3
            ]);
        }

        return $user->id;
    }

    /**
     * 更新用户的信息
     * @param array $data
     * @return bool
     */
    public static function updateUserInfo(array $data)
    {
        $validate = new ApiUserValidate();
        if (!$validate->check($data)) {
            throw new ParameterException([
                'msg' => $validate->getError(),
            ]);
        }

        $static = static::find($data['id']);

        // 处理用户的加密数据
        // 判断是否有加密的数据
        if (empty($static->unionid)) {
            if (isset($data['encrypData']['encryptedData']) && !empty($data['encrypData']['encryptedData'])) {
                // 解密数据
                $decrpt_data = self::handleUserEncryData($data['encrypData']);
                if (!empty($decrpt_data) && ($decrpt_data['openId'] == $static->openid)) {
                    $data['unionid'] = $decrpt_data['unionId'];
                }
            }
        }

        $result = $static->allowField(['id','unionid','nick_name','avatar_url','gender','from'])
            ->save($data);

        if ($result !== false) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 通过微信网站应用的授权登录更新用户信息
     * @param $user_data
     */
    public static function updateUserInfoByWebApp($user_data)
    {
        $static = static::where([['id','=',$user_data['id']],['from','=',3]])
            ->find();

        if ($static) {
            $static->allowField(['id','nick_name','avatar_url','gender'])
                ->save([
                    'nick_name' => $user_data['nickname'],
                    'avatar_url' => $user_data['headimgurl'],
                    'gender' => $user_data['sex'],
                ]);
        }
    }

    /**
     * 通过微信公众号网页应用的授权登录更新用户信息
     * @param $user_data
     */
    public static function updateUserInfoByOCOAWebApp($user_data)
    {
        $static = static::where([['id','=',$user_data['id']],['from','=',2]])
            ->find();

        if ($static) {
            $static->allowField(['id','nick_name','avatar_url','gender'])
                ->save([
                    'nick_name' => $user_data['nickname'],
                    'avatar_url' => $user_data['headimgurl'],
                    'gender' => $user_data['sex'],
                ]);
        }
    }

    /**
     * 更新用户的Token对应的状态信息
     * @param array $data
     * @return bool
     */
    public static function updateUserTokenStatus(array $data)
    {
        foreach ($data as $name => $value) {
            switch($name) {
                case 'status' :
                    if (get_wx_config('mp_auth_user') == '开启') {
//                            (new UserToken(''))->updateUserTokenByUID($data['id'],'scope',((intval($value) == 1) ? ScopeEnum::USER : ScopeEnum::GUEST));
                    }

                    break;
                case 'third_status':
                    if (get_wx_config('mp_auth_third') == '开启') {
//                            (new UserToken(''))->updateUserTokenByUID($data['id'],'third_scope',((intval($value) == 1) ? ScopeEnum::USER : ScopeEnum::GUEST));
                    }
                    break;
            }
        }

    }

    /**
     * 处理用户授权信息中的加密数据
     * @param $data
     * @return array|mixed|string
     */
    private static function handleUserEncryData($data)
    {
        $session_key = MpApiUserToken::getCurrentTokenVar('session_key');
        $appid = get_wx_config('mp_app_id');
        // 判断签名是否符合要求
        $str = $data['rawData'] . $session_key;
        $str = sha1($str);

        if ($data['signature'] == $str) {
            $wxBizCrypt = new WXBizDataCrypt($appid,$session_key);

            $decrypt_data = '';
            $wxBizCrypt->decryptData($data['encryptedData'],$data['iv'],$decrypt_data);

            $decrypt_data = json_decode($decrypt_data, true);

            // 判断appid是否一致
            if ($decrypt_data['watermark']['appid'] != $appid) {
                return [];
            }

            return $decrypt_data;
        }

        return [];
    }
}